package md.specialEqp.inspect;
//任务单，检验的业务起始点。

import com.querydsl.core.annotations.QueryInit;
import graphql.relay.Connection;
import graphql.schema.DataFetchingEnvironment;
import lombok.*;
import md.cm.unit.Division;
import md.cm.unit.Office;
import md.cm.unit.Unit;
import md.specialEqp.BusinessCat_Enum;
import md.specialEqp.Eqp;
import md.system.User;
import org.fjsei.yewu.filter.Node;
import org.fjsei.yewu.filter.UserBase;
import org.fjsei.yewu.filter.Uunode;
import org.fjsei.yewu.util.Tool;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

//旧平台1个TASK映射1个ISP{可以多分项SubISPid}；Isp流转后出报告内容。
//这里放置每次作业时刻定夺动态的参数。
//如果两台同时进行检验的，按收费总额的90%收(单一次派工出去的/单任务?同种设备数) 开发票INVC 一对多 Task; 如何确认证明呢/处理进度若不一样/那个环节谁可以。
//TODO: Isp Task 关系哦 1:N? 1:1?  多分项报告 WF_TODO;
//部门分配给单OFFICE_ID;科室分配{单个=组长？PROJ_USER_ID},=> 派工;责任人PROJ_USER_ID,任务负责人==.E_PROJ_USER_ID'任务负责人==责任工程师==负责人;编制人属于检验人之一。
//派工人ASG_USER_ID:可以是?编制人或责任人;ISP_USER编制/检验人JY_MEN，审核PROJ_USER_ID CHEK_USER_ID：等级较高=科室主任；批准APPR_USER_ID：业务上算最高级别=中层干部。
//部门分配科室分配派工人竟然全是编制人自己？奇葩。 编制人{写报告的人}属于检验人员之中主要人员。

/**任务：业务运作驱动的发动机,掌控企业效率。
 * 旧平台Task只能挂接单个Eqp,新平台允许多个设备,考虑收费凭证关联，进度不一原因，Task底下多个设备要求归属单一个付款单位=服务对象单位。
 * 对特检设备检验检测企业，业务可能不关联设备，关联监察在库设备，关联非监察关注的设备。
 *  生成检验需求的作业工单，预设定收费参数。
 * 开发票相关。合同和协议申报相关。 年初批量生成任务,SDN报检平台用户主动发起的任务;不同业务类型拆开，
 * 同一个单位的多个设备若作业地点相互距离太远{文字地址就能看出}的，最好要拆开设置独立的Task。
 * 聚合型任务参数字段：若每个子任务实际不一致的就不要设置，看实际情况。
 * 单个Eqp的Task实际应当与Isp合并的。多个子任务只是一起分配给某责任人{省掉些消息通知或页面输入}，汇聚型任务单-拆解子任务；
 * Task是流水性质的，记录存储有效期限较短，任务终结1个年完整后（统计利用完成了）可能就清理掉，好比程序后台日志文件一样时间太久了失去意义。
 * 若Task没有终结或绩效和检验历史统计模块还没有把该Task统计过的，就不要删除。
 * 不同业务类型OPE_TYPE拆分成不同Task。同一个Task底下的Isp的业务类型OPE_TYPE必须相同，都准备派工给同一个责任人的;
 * 如果两台同时进行检验的，按收费总额的90%收(单一次派工出去的/单任务?同种设备数)； 多个Isp捆绑审核，捆绑进度条/复检呢，一起做;自由裁决权。
 *Task是业务发起起点，都必须有个任务。
 * Eqp.Task.Isp三个模型关系理顺： Eqp是目标永久库, Task是业务驱动每年结算后过期数据出清, Isp是业务载体提取的长期存储库记录。
 * 任务表没有直接关联某个设备的；通过Detail再关联到Isp最后间接关联Eqp。
 * 任务派工：实际应该分解出更多步骤：初始派工1=分配人到位，[报告编制可以开始了]，修正派工2=报告类型，分项报告和收费参数确认；而报告编制阶段=+同时计算收费和发票关联。
 *在年初或季度增补定期自动生成Task，其它的业务是随时申请产生的；在任务到期日之前提前地部门分配到科室再二次分配给负责人；负责人最终派工开始检验实际的工作，目标在任务到期日之前达成报告终结。
 * 任务层层分解，总体任务数量各类型业务所需工作时长总量会不定期的估算揭示，各级都会调整预期的Task派工和推进进度。
 * 历史数据统计？批处理检验成果：定检比率，工分等每一年统计等批处理需求的，考虑另外导出历史或快照的数据[按照截止日期?重复漏掉主键Task.id+status]，这样Task表就能尽快吧旧数据删除掉了。
*/

@Getter
@Setter
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder=true)
@Table(indexes={ @Index(name="task_servu_id_idx",columnList = "servu_id",unique=false)
} )
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Fast")
public class Task implements Uunode {
    /*@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "commonSeq")
    @SequenceGenerator(name = "commonSeq", initialValue = 1, allocationSize = 1, sequenceName = "SEQUENCE_COMMON")
    * */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;

    /**发票开票的缴款单位，服务对象单位: 不一定等于设备台账的使用单位, 也不一定等于签订业务协议的签字单位。
     * 发票开票的缴款单位不一定就是交钱的实际支付人或单位; 可能没关联设备。 servu不一定是使用单位，有可能是工程安装公司。
     * 每个Task只能安排一个服务对象(使用单位),没有挂接Eqp的报告制造监检不需要指定Eqp的任务也只能有一个用户单位{申请单位,生产单位}。
     底下每个Isp也会设置关联单位的，【特别注意】两个冗余字段的更新同步。 Isp是长期储存，Task是短期储存。
     通常情况：底下每一个ISP的三元组< servu + EQP_TYPE + bsType >必须一样的，才允许派工啊。
     允许关联的Eqp可能是多家不同的使用单位，Task只需管收钱开发票的账务单位和协议签订甲方乙方确保一致性。
     */
    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn
    private Unit  servu;

    /*责任人。
     * 基本型任务=旧平台任务那样的只能关联单个Eqp的。
     * 聚合型任务，关联多个Eqp设备。聚合型任务=页面输入的分解步骤：最终直接生成设备任务。
     * 显示上可以过滤树形状分别列表。直接搜设备加业务，受理部门不选不等于任务部门。
     * 统计过滤可分别针对基本型/聚合型; OLAP模块另外抽取。
     * 合同协议关联多个任务设备，发票关联多个任务。形式意义的合同:任务是多对多关联{?合同可能撤销后重新生成但是任务可以利用旧的,新的合同号新的收费}。
     * 1份合同协议可以关联多个Task任务。
     * 发票仅仅只是链接和统计用途：1个发票可以关联多个Task,单个Task也可以关联多个发票,N:N。发票给同一个缴款人;TB_INVC_ASSDET；
     * 合同协议仅仅只是链接和记载用途：1份协议合同可以关联多个Task,N:N。合同拆分Task应该选定一个对口业务部门(部门地域管辖)。
     * 1个Task底下选择关联设备种类必须相同{方便分配给唯一个检验部门干活}，总之只能单个部门，有些部门不能执行某个业务类型。
     *ISP_TYPE机电1承压2 是种类附属的, BUSI_TYPE法定1委托2 是业务以及监管责任附属的的；
     *需要长期存储的字段 最好摆放在Isp中否则Task过期丢失。
     * 制造监检考虑从Isp中恢复已有的数据来复用。制造监检没有关联设备，但是有单位,业务类型，附带设备类别有就是没有具体的设备?。
     *1个Task所对应的发票的缴款人同一个单位的{代缴人，应缴人=使用单位},不支持多个缴款人, Task挂接发票申请/账务记录。
     * 单独一个Task应当是唯一个使用单位的业务和设备(可多个)，为了优惠减免考虑 + 方便分配给同一组检验人员干(地域临近), 同种类的设备同一单位才享受优惠{独立协议或合同来规定收费金额除外}。
     * Task层面预留收费调整机制{审批人？}。
     * 法定定检自动生成任务？同一个单位还可能地域位置分开很远{地址}，不同单位的反而地域临近的可以一次性打包接活了{多个任务按照地理聚合?不同的定检到期时间预约}。?分配机制?负责人灵活自主？
     * 部门同一个科室的新任务，按照地理划分设备归属。科室派工 提供机制把同时间段多个任务按照地理聚合分派同一个责任人去做；分配到每个责任人的承接任务预计工时量。
     * 1个Task底下每个Isp的具体参与检验人员以及审核人员都必须相同，Isp报告终结进度可以不一样；但是Task有一个总的完结机制(收费完成了),意外拆分或裁减Eqp。
     */
    //@Deprecated
    //private String  director;    //PROJ_USER_ID, 单独一个人。

    /**责任人, 组长负责制，只能单个人, 权限最大的。
     * graphQL模型文件定义改成liabler: UserBase会导致.SchemaClassScannerError: Two different classes used for type UserBase:错,需要换个壳给graphQL。
     * */
    @ManyToOne(fetch= FetchType.LAZY)
    private User liabler;

    //1个任务有n个设备,没有关联设备，虚拟设备（煤气罐系列化的设备号01..09排除05}），管道特别[选择几个单元为了报告/计费]。
    /* Eqp这里仅仅是提供几个设备号关联，更加明确的关系还得到Isp底下字段才能真正敲定那些设备。
    Task单独报告的可没有设备关联；
    //我是关系维护方,必须在我这save()，　缺省.LAZY;
    @ManyToMany
    @JoinTable(name="TASK_DEVS", joinColumns={@JoinColumn(name="TASK_ID")}, inverseJoinColumns={@JoinColumn(name="DEVS_ID")}
                //indexes={@Index(name="DEVS_ID_idx",columnList="DEVS_ID")}
            )
    private List<Eqp> devs;
    【重大变更】 Task底下不挂Eqp了，要在Task.isps.Eqp才能获得设备信息， 请前端注意！
    */

    /**OPE_TYPE 业务大类， 有的还需要配合REP_TYPE来区分 更详细的工作内容模板。
     * 这里的bsType/entrust优先覆盖Isp.bsType/entrust; 【注意】一个任务bsType/entrust只能保持唯一性。
     * 业务类型 OPE_TYPE：统计？模板？ TB_DICT_OPETYPE似乎没内涵36个压缩到实际28个/委托法定=
     * 法定还是委托的 是 监管归属属性，收入统计归属/报告制作差异。
     * 承压还是机电的 是 设备属性，部门归属，角色大尺度划线权限，发票区分财务开票点。
     * 同一个Task底下的Isp的业务类型OPE_TYPE必须相同，都准备派工给同一个责任人的。
     * "3", 全面: "358230" 今年条数含作废的;
     * "603",委托的: "1624"}
     * "8", 外部: "93300"}
     * "608",委托的: "720"}
     * "13"其它: "63104"} 主要是"700003"安全阀离线校验,"58416条; "700001"安全阀在线校验, "4573条;"EQP_SORT":"FZ00"EQP_VART":"7310",没有进入Eqp？
     * "2"安装监检: "33340"}
     * "1"制造监检: "8747"}
     * "16"首检: "7943"}
     * "19"热效率测试: "5920"}
     * "11"检测: "5325"}
     * 业务类型除了3，8，603，608之外的，很少集中生成任务？:
     老旧电梯评估"618", 9: "45"} 年初大批生成的:评估.
     热效率测试="19", 9: "5160"} 年初批量手写命令加: 710006 710029 到了日期遇见停用不要做了。
     其它=13 "13", 9: "4955"} 随时加 700003 700001 400041控管理系统定/法定{检验时附带生成任务} 400040
     安装监检"2", 9: "3080"} 监检TASK_DATE没约束力甚至比CREATE_DATE还早，管道拖延时间很长
     制造监检"1", 9: "942"} 200001压力容器产品安全性能监督检验 232001 800017 100001 200005；TASK_DATE没约束力 FACT_PRIC=50 多份Task/Isp/REPORT_COD
     首检"16", 9: "841"} 500023叉车首次检验 400045 500024 500025；TASK_DATE没约束力; INVC_COD复检没变。
     检测"11", 9: "321"}  710001法定/工业锅炉水质检验 710002锅炉水汽质量检测｛检验部门是节能中心不是预分配的电锅中心｝人工搜索满足条件的再做添加;
     */
    @Enumerated
    private BusinessCat_Enum bsType;
    /**是委托的吗, 牵涉收费管控。法定的收费不能变动，委托的可以折扣？
     * 特殊任务和报告可能根本不需要关联发票的，不需要单独做收费；在签订协议上总金额/按年结算；根据业务和单位来审核=排除收费管控环节。
     * */
    private Boolean  entrust;

    /**挂接多个业务记录Isp; 注意！ Isp是长期存储的，而Task只能短期保存的。
     * 可允许拆分或合并Eqp进入一个任务,一部分先行终结而拆开掉;
     * 实际就是多个设备； 所以上面 private List<Eqp> devs; 可以作废掉了！
     * 可能不同的业务作业类型OPE_TYPE? ,不同OPE_TYPE有各自的报告结论证明? 只会有唯独一个OPE_TYPE，所以Isp唯一:@OneToOne
     * 单个Task针对同一台设备 也会有多个业务类别 产生不同种类报告；业务或报告不一定都有挂接某个设备。
     管道特别每个单元下次定检日期都不一样(可分开多批次的任务),任务生成时旧的核对单元并且加业务锁：应用层锁具体规则代码控制。
     当前管道单元最新已生成task关联关系表[任务锁],直接在PipingUnit增设'当前task'=锁；
     Isp在任务创建时刻指定设备号就得同时创建Isp。
     //todo:同一批次多台设备的收费优惠政策。如何证明：查验审核。
     对方ISP去维护这个关联关系。
     一个任务单Task包含了多个的ISP检验记录。 　任务1：检验N；
     默认fetch= FetchType.LAZY; 而mappedBy代表对方维护关系  EAGER
     OneToMany用Set集合而不用list
     【注意】Detail可能有很多条：业务类型与法定委托必须一致的，业务负责人只能同一个人。开票单位servu也是同一个的。
     派工后部门以及科室也必须是同一个的，所以设备类型尽量保证一样这样唯一一个业务科室才能承接的了！
     【约束】status必须同步上，不同业务ISP/Detail的，保持Task状态统一性,一起派工和一起完成！不然只能拆分？。
     多个Detail的：名义上的任务日期date要差不多一样吧(看负责人意见)；名义作业地址opAddress也尽量能够同一个地点的吧(看科室需要而定)。
     */
    @Builder.Default
    @OneToMany(mappedBy = "task")
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL,region ="Fast")
    private List<Detail> dets =new ArrayList<>();

    /**责任检验部门， Task要最终派给责任人，所以科室部门都是隐含敲定的。
     * 作为配合身份的部门，可以私底下约定收入的分成，仅供年终核算统计用途的；
     * 可能附带一个配合部门，收入提成比例%；
     * Task有收入证明，联合检验适用的配合部门有共享分成，发票是实时的且是主要检验部门独占收入，配合部门年底提供统计证明指示应当提成收入。
     * 派工报告编制审核审批工分计算不涉及到配合检验部门的具体分工，配合部门人员工作当做隐形，收入提成比例由责任人设定就是，配合部门不参与平台其它操作。
     * 联合检验配合部门最多设置一个。
     * 同一个Task底下的每个设备都一样，关联收入的，一致化处理，不能每条Isp[就是Eqp不同]搞得不一样。
     * F_DICT_DEPTNAME(A.EQP_ISP_DEPT) , HRUSER.TB_DEPT_INFO
     * 【奇了】若后端是关联实体如Task.Division dep;再假如graphql模型文件中改成定义dep: String会导致前端将接收到的是dep实例toString输出的字符串。
     * */
    //private String dep;   //liabler未确定之前不知道是哪个投给部门的；
    @ManyToOne(fetch= FetchType.LAZY)
    private Division dep;

    /**责任人派工； 一般的都是同一个科室底下的人员 才可作为检验员
     * 【奇怪】：实际Task只需要负责人就够了，为何非得折腾出个一定是某部门的一定是某一个科室的。负责人User自身肯定应当有个所属的科室部门吧！会不一致了？
     * dep和office两个字段是过程性质--非强制性，工分绩效年度统计的平台才会关注功劳是到底哪个部门科室的。
     * */
    //private String office;   //liabler未确定之前不知道是划给哪个科室。
    @ManyToOne(fetch= FetchType.LAZY)
    private Office office;

    /**状态： 新生成未定部门，部门分配，科室分配，责任人派工，已派工，等待复检，等待整改反馈，已完成，作废；
     *   TB_TASK_MGE.TASK_ALLO_STA=0部门分配{未派工作废} 1科室分配{未派工作废} 2责任人派工{作废/未派工/已完成},@ 3分配派工完成{已完成}；
     *   .TASK_STA=0.未派工；@ 1.已派工；2.等待复检；3.等待整改反馈；4.已完成；5.作废；
     * 责任人派工后的状态是[TASK_ALLO_STA=3,TASK_STA=1];
     * 不合格报告编制 流转审核-》允许复检，等待复检状态TASK_STA=2。
     * SDN有申请？ 发现反馈好, Task复检派工按钮-》TASK_STA=3等待整改==等待检验员再次编制报告和再做流转Isp审核。
     * @ 所有Isp都流转终结+收费回款完成==》才可以：设置TASK_STA=4已完成；
     * 未回款CURR_NODE: "106"任务=已完成#也行？报告已打印了；TB_CERT_MGE<ISP_ID,ASS_ID>卡在回款+报告未发放；
     * */
    private TaskState_Enum status;       //未初始化的=null; 也算一个Enum状态可能性;
    /*关联 发票s: 多对多？ 发票特殊处理：实际约束应该是：要么一对多，要么多对一，？真正意义上的多对多: 代码上校对约束。
    【发票和任务关联关系】具体规则待定：确保收费确认正常，票款任务两清。
     * 1张发票对应多个Task的合计金额应该等于发票票额。
     * 1个Task对应多张发票的合计金额应该等于任务实际收费额。
     * 框架协议或总金额年度合同汇算的有协议包揽的牵涉的任务Task的收费对应的发票：依照审批人的意见执行，特殊情况=不校对金额和汇总差额，仅需关联发票并审批后就可以算任务完成。
     * 整改反馈内完成的复检不额外收费{就给 2 次机会}，#一次机会超期的终结{收费完成了吗}，
     * 第二次申报再次检验,再回来就被当做新的Task,超期复检收费优惠？。
     * [旧平台计费] 收费参数 TB_DICT_FEEFIELD 有62条/交互时能改的参数，算法标准参数 TB_DICT_FEESTANDARD 收费目997条；
     * 任务和开票申请可能多对多关联。TB_INVC_ASSDET有1张发票对4个Task而且是3次不同时间做的关联发票。
     * 发票的显示依据说明：TB_INVC_DET=按收费项目做聚合；查看发票的项目明细=2行：实际4个任务=3容器+1台管道设备归类合并,可手动修改。
     * TB_INVC_MGE.BUSI_CHECK_USER_ID"发票业务审核人(多+人)"
     * */
    private String  invoice;

    /**
     * 任务的名义作业地址，用于Task合并聚合派工，临近地点的任务临近时间的都派给同一个责任人。
     * 实际可以把底下多个Isp的实际地址进行中心位置纬度经度;或者首要Address地址。
     * 不见得都是一个地区的。特殊任务有可能跨越大地域的。
     */
    @Deprecated
    private String  opAddress;

    //【恼人的】中间状态值? ，前后端交互操作的过渡状态机制变量，很容易不一致，带来歧义和繁琐的确认流程。前端后端耦合度大，其它更好方案？
    /** 自动计算折扣收费理由： 所有Detail(多个Isp)收费确认后
     * 并非是前端输入的备忘理由 说明！！
     * 后端自动计算折扣，后端自动附加的说明。 前端不能自主选择是否启用这些优惠折扣。
     * json: {"B101":"单项管道检验总长度超过10公里，不足30公里", "B103":"电站锅炉水汽质量检验时，如果两台同时进行检验的",...}, 耦合度更强?
     * 【约束】前端看到的理由说明，文字串有限个数；所以Task层次的这个插入点的折扣收费程序应该尽量避免，尽量少遇见，更不要同时出现很多个折扣理由。
     * 假如业务计费产生变动，那么feeOk，disfee，charge必须复位成初始状态，需要再次确认审批。
     */
    private String  dreason;
    /** 自动折扣后任务应该收费金额：  disfee>=0;
     所有Detail(多个Isp)收费确认后并且自动计算折扣后最终合并金额。discount 已经折扣之后的Task总收费。
     假如dreason=null没有半点自动折扣理由的；disfee应该=所有Detail/Isp的已经确认收费金额合计。
     ‘任务金额汇总‘按钮触发的Task级别自动折扣计算 。
     */
    private Double  disfee;
    /** 任务实际收费额： 整个任务Task最终批准的收费金额(需人工确认)。 charge>=0;
     * 正常法定检验应该等于disfee； 委托检验或特殊理由的优惠的其它业务收费才会出现charge!=disfee的情形。
     * 对于charge!=disfee的情况：确认通过，需要审核批准？ 需要关联申请表ID 发票业务审核人;
     * */
    private Double  charge;

    //【恼人的】中间状态值? ，前后端交互操作的过渡状态机制变量，很容易不一致，带来歧义和繁琐的确认流程。前端后端耦合度大，其它更好方案？
    /**涉及到了某一个Isp的收费需要重做的feeOk必然也得重做。
     * 实际收费额需要审核批准的那些情形在批准之前也是feeOk=false; 不需要审批的前端编制人本人确认即可，不需要领导批准。
     */
    /**延期检验日期1：ABNOR_ISP_DATE1 相对NEXT_ISP_DATE1下次检验日期1
     * 检验业务状态关心字段。实际关联了延期检验申请单，申请批准后的/申请延期日期。字段关联直接转为本地状态复制字段，注意保证一致性。
     延期是业务开始前后？没做完都算的，形式上！，Task是发起者。TaskState_Enum ?竟没有延期什么事？
     * */
    // @Temporal(TemporalType.DATE)
    // private Date did1;
    /**延期检验日期2：ABNOR_ISP_DATE2  超期未检+统计; Task是发起者。
     * 【设置该字段】=预定下次定检日期2到了，检验任务未搞定，设置延期，就不会上报监察重要事项了，否则自动申告给监察。
     * 字段关联直接转为本地状态复制字段，注意保证一致性。
     * 【管道特殊！】 可能多个任务同时在做，到底是那一条Isp要求延期进行啊。同时配合Task的延期标志来判定。根据检验单元明细nxtd12+Isp;
     * */
    // @Temporal(TemporalType.DATE)
    @Builder.Default
    private boolean  feeOk=false;


   // private Date did2;   当前date任务日期(可能已经延期过了)可以直接和设备台账的下检日期比对，来确定是否真的延期了，前端显示比较结果。
    //【判定是否超期告警!】：下检日期！=null: 下检日期<Today.Now(), ?isp2?!=null : isp2.task.date<.Now() && isp2.report.stm.sta==END ;

    /**名义上的任务日期 截止日: 务必在这个日期之前完成任务, 超期的工分业绩统计平台依据{Isp报告发放时间，Task完成时间}。
     * date对于每个Detail应该是同一时间点：约定业务完成的截止日期，可适当提早点进行法定定期检验。
     * 多设备必须相同一致，否则多台设备如何算一个批次计费; 一个任务多台设备应当同时终结(算最后一个设备完成为止)。
     *任务延期多台设备进度排斥呢：部分设备延期，考虑拆分掉，1个正常部分任务+1个延期部分任务。
     *延期审核;有延期至日期的任务，查询任务时间以延期至日期为准 DECODE(A.ABNORTO_DATE,NULL,A.TASK_DATE,A.ABNORTO_DATE) TASK_DATE,
     *同意延期后，TASK_DATE应当改成新的。旧的TASK_DATE=初始原定任务日。
     * ORACLE: 表名USER不能用，字段date不能用。
     * 何时才能开始编制报告?任务日期开始?截止日；任务日期= 完成率计算截止日。
     * ？任务日期 + 每一报告的预定截止天数。
     * 延期检验批准后date直接调整=新的截至日期。
     * 【约束】名义上的任务日期(不一定就等于报告书当中的检验日期)，多个Detail/Isp的也要尽量一致啊，同一个约定任务日期。
     * 延期检验申请批准后：尽可能使得date=延期后的日期。
     * */
    //@Column(name="TASK_DATE")
    private LocalDate date;

//  TODO： 延期检验申请批准后，延期标志。  TaskState_Enum ??竟没有延期什么事？旧的TASK_DATE=初始原定任务日。？
//关联的 延期申请单。  ，==延期标志; 标注出 旧的TASK_DATE=初始原定任务日。 ABNORTO_DATE ,ABNOR_ISP_DATE1
    /** 延期标志。
     * 旧的TASK_DATE=初始原定任务日。
     * 如果没有延期过{批准的}的话，设置origd=null;
     旧检验：ABNOR_ISP_DATE1 =20条;  太少见  ABNOR_ISP_DATE2== 842条；
     旧监察：ABNOR_ISP_DATE1= 11242条,  ABNOR_ISP_DATE2== 85568条, 实际很多是不合逻辑的，没清理数据，甚至ABNOR_ISP_DATE=下次检验日期的。
     const ispStat1= !isp1?.report.stm? '完成': isp1?.report.stm.sta==='END'? '完成': isp1.task&&isp1.task.origd? '延期检验': '进行中(正常)';
     ## isp1?.report.stm=NULL?  ? isp1.task.origd==NULL; 若是旧的平台报告同步进来的ISP:关联task=null+关联report=null##
     ispStat1!=='完成' ？？isp1.task?.date 延期检验   ABNOR_ISP_DATE2  ABNOR_ISP_DATE1
     todo: 延期检验申请批准后：尽可能使得date=延期后的日期。而origd=原定任务日期代表拖延多久了。
     * */
    private LocalDate origd;
    /** 检验归属某个特检院
     * 支持多个检验机构都能使用本平台出报告和业务流程的对所有检验机构都能共同支持。
     * @NotNull 对于已经存在的null数据不会报错。
    * */
    @NotNull
    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn
    private Unit  ispu;     //缺省 =福建省特检院。

    //todo:在化学介质、易燃介质等毒性危害和爆炸危险环境下进行检验作业或接触生产性粉尘作业危害程度在II级（含II级）及II级以上环境下进行检验作业的加收30%；
    //设置加急，发起人？验证时间截至期限。
    //加急检验（三个工作日取检验报告）加收20%; 条款？        =? 影响Isp流转催促/审核等环节了。
    //廉租住房、公共租赁住房、经济适用住房和棚户区改造安置住房等保障性安居工程项目免收行政事业性收费和政府性基金=扯呼; 临时起的帽子，属性? 例外申请途径/批准配置。

    //类型： 常规任务
    //超出整改反馈期后复检任务自动终结； 多个Isp其中有部分Eqp不合格的，多台Eqp一起受到流转阻碍，可允许拆分独立终结{[合格s]task2[不合格s]}Task1审批回款允许提前终结。
    //BUSI_TYPE 法定1/委托业务性质 BUSI_TYPE=2委托的；仅用于区分报告的格式内容以及收费，
    //ISP_TYPE{检验范畴1机电2承压3}， 仅用于区分报告的链接菜单入口{列表框的大一层级分类}大类科室分配和收费会计中心；

    //JOIN_DEPT_ID ,IS_JOIN_ISP, 1, '联合检验', '2','任务调配/变更','0常规' TB_JOIN_ISP_INFO 仅仅提示用{没有收入工分分配}只能通知不能编制报告JOIN_MEMO,发票都是单个部门的/年终搞个核算轧差账单;
    //IF_THREEMONTHS,IF_HAVNEXTTASK 作废字段，
    //任务状态及结束分类标记：F_DICT_RISPPERRESULT(A.RISP_PER_RESULT) UNISP_TYPE_NAME，2003,2001延期检验... 及时率计算{因为延期而结束}


    /*  旧的kickstart底层中间件情形用的 ? directive @dbpage ; 而对新Spring for graphQL可弃用了。
     *  @dbpage 跳转graphQL模型到接口函数：##实际不会运行到这里!。
     * 为什么？把集合字段转移出去。
     * 这里加@dbpage指示，跳转另外一个接口函数: 无法在Entity类里面操作库表的查询。
     * Relay针对字段private Set<Isp>  isps=new HashSet<>(); 最后DataFetchingEnvironment env参数是自动添加的。
     * 怎么改都没用啊！太积极了ryList(int first,) 都会直接加载isps<Isp>了。
     * 最接近触发查询语句的代码来自：
     * jdk.internal.reflect.NativeMethodAccessorImpl#invoke0  以及和graphql有关的最接近代码出自：
     * graphql/execution/instrumentation/dataloader/DataLoaderDispatcherInstrumentation.java:86
     * 无论怎么改，graphql内省时查字段都会直接触发1对多Set<Isp>集合字段的查询，直接查出全部数据的。
     * 还需要添加排序字段参数，甚至过滤字段参数的处理？ 看前端需求。
     *模型名字不一致：graphql.kickstart.tools.SchemaClassScannerError: Two different classes used for type DetailConnection:;
     *若Task底下很多的设备检验数量的：根据Eqp 或 detail.ident{不需要提前配置设备的，工作时刻即时性增加检验对象标签，无法预先准备每条Isp检验数据,派工不及时}进行过滤。
    */
//    @Deprecated
//    public Connection<Detail> detail_list(int first, String after, int last, String before, DataFetchingEnvironment env) {
//        /*        //MemoryListConnection connection=new MemoryListConnection(isps,10,"isp",10);
//                //跳转接口模式: @dbpage; 从User或者Task内省而来的，并非直接给出参数字段去查询的独立接口Query模式。
//                //不需要处理Relay参数的，env也保存Relay参数。
//                //需要添加排序字段参数，甚至过滤字段参数的处理? new MemoryListConnection<Isp>(isps,10,"isp").get(env);
//                //因为是List<T> data；还不会报错！可是注意！Isp 改成了 Detail了；
//                return new MemoryListConnection(isps).get(env);*/
//        //跳转接口，这里放空。跳转接口模式: @dbpage; 从User或者Task内省而来的，并非直接给出参数字段去查询的独立接口Query模式。
//        return null;
//    }
    /** 转换输出给前端的graphQL类型，从原生的User改成UserBase。
     * graphQL接口中间件自动优先使用返回类型一样的函数作为模型的字段映射：就是实际这里liabler()替换掉getLiabler()，但是对java后端其它代码没有影响。
     * graphQL模型文件定义改成liabler: UserBase会导致.SchemaClassScannerError: Two different classes used for type UserBase:错,需要换个壳给graphQL。
     * 前端越权内省字段liabler { photoURL } 后端就会报错了：.GraphQL  : Query failed to validate :#无法泄露UserBase中没有发布的字段,User才有photoURL字段。
     * */
    public UserBase liabler(){
        return this.liabler;
    }
    /**名义设备种类 EQP_TYPE,最早添加的第一条Detail对应的设备种类;
     * 仅提供接口给前端的，通过graphQL模型提供的Task.type伪字段； 注意，java后端不允许用它！
     * */
    @Deprecated     //新版没法运行到这
    public String type(){
        if(!dets.isEmpty()) {
            Detail det= dets.get(0);
            Isp isp= det.getIsp();
            if(null!=isp && null!=isp.getDev())
                return isp.getDev().getType();
            else
                return det.getType();
        }
        else return  "";
    }
    /**当前任务变更人; 谁生成的任务。
     * 批作业生成=null;
     * */
    @ManyToOne
    private User crman;
    /**修改时间， 生成的时间。
     * */
    private LocalDateTime crtime;
/* --起重机附属装置不参加定检率考核 SET A.RISP_PER_TAG = 0 : SUBSTR(EQP_COD, -1, 1) IN ('J', 'F');--从后面倒数第1位
    定检任务考核标识均设置为“已注册设备参与考核”。本年度已有委托性质的非考核任务，更改业务性质和考核标识即可，以免设备更改为注册状态后，委托任务转为法定考核任务。
     --管道 没有注册的生成 法定定检任务，但是RISP_PER_TAG=2
* */

    /**关联协议：
     * 协议状态决定任务状态可能性，派工要注意协议状态。
     * */
    @ManyToOne(fetch= FetchType.LAZY)
    private Agreement agreement;
}


/*
如果是EAGER，那么表示取出这条数据时，它关联的数据也同时取出放入内存中;用EAGER时，因为在内存里，所以在session外也可以取。
如果是LAZY，那么取出这条数据时，它关联的数据并不取出来，在同一个session中，什么时候要用，就什么时候取(再次访问数据库)。
但在session外就不能再取了,failed to lazily initialize a collection报错；因为操作实际被多场次的数据库session分开。
查询一个graphQL按策略执行器（因为性能要求）＝＝〉并发分解的和异步的策略＝＝〉导致分配到了多个数据库session了。
*/

/*
下次检验日 {预设定大小保养时间},检验等级规模。检测记录，检测规定时间。
if等级1/3/的，耐压试验6年{2.5年}一次。https://wenku.baidu.com/view/369ebf72760bf78a6529647d27284b73f3423615.html
旧平台任务分配分派 Group分组 EQP_AREA_NAME,USE_UNT_ADDR,.BUILD_NAME,设备TASK_LKMEN=USE_LKMEN,TASK_PHONE=USE_PHONE,.MANT_UNT_NAME,A.JOIN_DEPT_ID；组合子任务可选择。
法定定期的任务：监管敲定法定检验机构-》检验机构分配部门(联合检验部门)-》后台维护或自动提前生成任务-》部门分配给科室-》科室分派给责任人-》责任人派工敲定检验员-协检员-检验时间。
其他协议诱导任务：合同及协议受理-》检验机构分配部门(联合检验部门)-》生成具体设备任务-》部门分配给科室-》科室分派给责任人-》责任人派工敲定检验员-协检员-检验时间。
联合检验?收入工分分配  部门收入，人员工分，
*/


/* @数据库修改脚本：
CREATE INDEX task_servu_id_idx ON public.task USING btree (servu_id ASC) STORING (bstype, charge, date, director, disfee, dreason, entrust, feeok, invoice, opaddress, origd, status, dep_id, ispu_id, liabler_id, office_id, crman_id, crtime);
    --不会删除unit office user的，考虑常用的过滤需求，#也没有请ES来帮忙#。
CREATE INDEX task_ispu_id_dep_id_office_id_bstype_index ON public.task USING btree (ispu_id ASC, dep_id ASC, office_id ASC, bstype ASC);
CREATE INDEX task_ispu_id_dep_id_office_id_liabler_id_index ON public.task USING btree (ispu_id ASC, dep_id ASC, office_id ASC, liabler_id ASC);
CREATE INDEX task_ispu_id_dep_id_status_index ON public.task USING btree (ispu_id ASC, dep_id ASC, status ASC);
CREATE INDEX task_status_ispu_id_dep_id_office_id_liabler_id_index ON public.task USING btree (status ASC, ispu_id ASC, dep_id ASC, office_id ASC, liabler_id ASC);
* */
